/*
 *  This file is part of ZiggyStardust.
 *
 *  ZiggyStardust is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  ZiggyStardust is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.wisc.csvParser;

import com.wisc.csvParser.plugins.DataColumn;
import com.wisc.csvParser.vocabProviders.IVocabProvider;
import com.wisc.csvParser.vocabProviders.*;
import javax.swing.JDialog;
import javax.swing.JComboBox;
import javax.swing.JLabel;

       


/**
 *
 * @author  user
 */
public class ValueObjectJPanel extends javax.swing.JPanel {
    ValueObject val;
    IVocabProvider vocabProvider = GlobalProgramSettings.vocabProvider;
    JDialog parentDialog;
    DataColumn columnObject;
    
    /** Creates new form ValueObjectJPanel
     * @param val The <code>ValueObject</code> to be displayed
     * @param parentDialog
     * @param colObj 
     */
    public ValueObjectJPanel(ValueObject val,JDialog parentDialog,DataColumn colObj) {
        initComponents();
        this.val = val;
        this.parentDialog = parentDialog;
        this.columnObject = colObj;
        
        if(vocabProvider == null){
            vocabProvider = new GLEONVocabProvider();
            vocabProvider.updateLocalVocab();
        }
        populateVocab();
        populateSelections();

        
        siteWarning.setVisible(false);
        sourceWarning.setVisible(false);
        aggMethodWarning.setVisible(false);
        variableWarning.setVisible(false);
        unitWarning.setVisible(false);
        utcOffsetWarning.setVisible(false);
        aggSpanWarning.setVisible(false);

        
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        siteCB = new javax.swing.JComboBox();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        sourceCB = new javax.swing.JComboBox();
        jLabel4 = new javax.swing.JLabel();
        variableCB = new javax.swing.JComboBox();
        unitCB = new javax.swing.JComboBox();
        jLabel5 = new javax.swing.JLabel();
        aggMethodCB = new javax.swing.JComboBox();
        jLabel6 = new javax.swing.JLabel();
        utcOffsetTB = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        sensorTB = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        duplicateCB = new javax.swing.JComboBox();
        saveButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        offsetTB = new javax.swing.JTextField();
        offsetTypeCB = new javax.swing.JComboBox();
        jLabel9 = new javax.swing.JLabel();
        aggSpanTB = new javax.swing.JFormattedTextField();
        siteWarning = new javax.swing.JLabel();
        sourceWarning = new javax.swing.JLabel();
        aggSpanWarning = new javax.swing.JLabel();
        aggMethodWarning = new javax.swing.JLabel();
        unitWarning = new javax.swing.JLabel();
        variableWarning = new javax.swing.JLabel();
        utcOffsetWarning = new javax.swing.JLabel();

        jLabel1.setText("Site:");

        jLabel2.setText("Variable:");

        jLabel3.setText("Source:");

        jLabel4.setText("Aggregation:");

        jLabel5.setText("Unit:");

        jLabel6.setText("UTC Offset:");

        jLabel7.setText("SensorID:");

        jLabel8.setText("Duplicate ID:");

        duplicateCB.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "2", "3", "4" }));

        saveButton.setText("Save");
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });

        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        jLabel9.setText("Offset:");

        try {
            aggSpanTB.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("##:##:##")));
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
        }

        siteWarning.setForeground(new java.awt.Color(204, 0, 0));
        siteWarning.setText("*");

        sourceWarning.setForeground(new java.awt.Color(204, 0, 0));
        sourceWarning.setText("*");

        aggSpanWarning.setForeground(new java.awt.Color(204, 0, 0));
        aggSpanWarning.setText("*");

        aggMethodWarning.setForeground(new java.awt.Color(204, 0, 0));
        aggMethodWarning.setText("*");

        unitWarning.setForeground(new java.awt.Color(204, 0, 0));
        unitWarning.setText("*");

        variableWarning.setForeground(new java.awt.Color(204, 0, 0));
        variableWarning.setText("*");

        utcOffsetWarning.setForeground(new java.awt.Color(204, 0, 0));
        utcOffsetWarning.setText("*");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jLabel6)
                            .addComponent(jLabel1)
                            .addComponent(jLabel3)
                            .addComponent(jLabel5)
                            .addComponent(jLabel9)
                            .addComponent(jLabel2)
                            .addComponent(jLabel4))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(offsetTB, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(offsetTypeCB, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(unitCB, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(aggSpanTB, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(aggSpanWarning)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(aggMethodCB, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(aggMethodWarning))
                                    .addComponent(unitWarning)))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(sensorTB, javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(utcOffsetTB, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 79, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(utcOffsetWarning))
                            .addComponent(variableCB, javax.swing.GroupLayout.PREFERRED_SIZE, 339, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(siteCB, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(sourceCB, javax.swing.GroupLayout.Alignment.LEADING, 0, 230, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(sourceWarning)
                                    .addComponent(siteWarning)))))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addComponent(jLabel7))
                            .addComponent(jLabel8))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(duplicateCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addComponent(saveButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(cancelButton)))
                .addGap(19, 19, 19)
                .addComponent(variableWarning)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(siteCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(siteWarning))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(sourceCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(sourceWarning))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(variableCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(variableWarning))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(aggSpanTB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(aggSpanWarning)
                    .addComponent(aggMethodCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(aggMethodWarning))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(unitCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(unitWarning))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(offsetTB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(offsetTypeCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(utcOffsetTB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6)
                    .addComponent(utcOffsetWarning))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(sensorTB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(duplicateCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel8))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cancelButton)
                    .addComponent(saveButton))
                .addGap(80, 80, 80))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        
        if(!checkRequired()){
            return;
        }
        
        try{
            save();
        }catch(java.text.ParseException pe){
            javax.swing.JOptionPane.showMessageDialog(null, "Trouble parsing aggspan, please check.");
            return;
        }catch(NumberFormatException ne){
            javax.swing.JOptionPane.showMessageDialog(null, "Trouble parsing input, please check.");
            return;
        }
        
        //if we get here, everything is OK, close dialog
        parentDialog.setVisible(false);
        parentDialog.dispose();
        
}//GEN-LAST:event_saveButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        parentDialog.setVisible(false);
        parentDialog.dispose();
    }//GEN-LAST:event_cancelButtonActionPerformed
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox aggMethodCB;
    private javax.swing.JLabel aggMethodWarning;
    private javax.swing.JFormattedTextField aggSpanTB;
    private javax.swing.JLabel aggSpanWarning;
    private javax.swing.JButton cancelButton;
    private javax.swing.JComboBox duplicateCB;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JTextField offsetTB;
    private javax.swing.JComboBox offsetTypeCB;
    private javax.swing.JButton saveButton;
    private javax.swing.JTextField sensorTB;
    private javax.swing.JComboBox siteCB;
    private javax.swing.JLabel siteWarning;
    private javax.swing.JComboBox sourceCB;
    private javax.swing.JLabel sourceWarning;
    private javax.swing.JComboBox unitCB;
    private javax.swing.JLabel unitWarning;
    private javax.swing.JTextField utcOffsetTB;
    private javax.swing.JLabel utcOffsetWarning;
    private javax.swing.JComboBox variableCB;
    private javax.swing.JLabel variableWarning;
    // End of variables declaration//GEN-END:variables
    
    private boolean checkRequired(){
        boolean everythingOK = true;
        
        everythingOK = everythingOK && checkRequiredCombo(siteCB,siteWarning);
        everythingOK = everythingOK && checkRequiredCombo(sourceCB,sourceWarning);
        everythingOK = everythingOK && checkRequiredCombo(aggMethodCB,aggMethodWarning);
        everythingOK = everythingOK && checkRequiredCombo(variableCB,variableWarning);
        everythingOK = everythingOK && checkRequiredCombo(unitCB,unitWarning);
        
        try{
            Double.parseDouble(utcOffsetTB.getText());
            utcOffsetWarning.setVisible(false);
        }catch(NumberFormatException nf){
            everythingOK = everythingOK && false;
            utcOffsetWarning.setVisible(true);
        }
        
        try{
            java.sql.Time.valueOf(aggSpanTB.getText());
            aggSpanWarning.setVisible(false);
        }catch(NumberFormatException nf){
            everythingOK = everythingOK && false;
            aggSpanWarning.setVisible(true);
        }
        
        return everythingOK;
    }
    
    private boolean checkRequiredCombo(JComboBox toCheck, JLabel warning){
            if(toCheck.getSelectedIndex() < 0){
                warning.setVisible(true);
                return false;
            }else{
                warning.setVisible(false);
                return true;
            }
    }
    
    private void save()throws java.text.ParseException,NumberFormatException{
        val.setSite((String)siteCB.getSelectedItem());
        val.setAggMethod((String)aggMethodCB.getSelectedItem());
        val.setDuplicateID(duplicateCB.getSelectedIndex()+1);
        val.setSite((String)siteCB.getSelectedItem());
        val.setSource((String)sourceCB.getSelectedItem());
        val.setOffsetType((String)offsetTypeCB.getSelectedItem());
        val.setUnit((String)unitCB.getSelectedItem());
        val.setVariable((String)variableCB.getSelectedItem());
        
        if(sensorTB.getText() != null && sensorTB.getText().compareToIgnoreCase("")!=0){
            val.setSensorID(Integer.parseInt(sensorTB.getText()));
        }else{
            val.setSensorID(-1);
        }
        if(offsetTB.getText() == null || offsetTB.getText().compareTo("") == 0){
            val.setOffsetValue(Double.NaN);
        }else{
            val.setOffsetValue(Double.parseDouble(offsetTB.getText()));
        }
        
        //Get variables requiring parsing
        val.setUtcOffset(Double.parseDouble(utcOffsetTB.getText()));
        
        val.setAggSpan(aggSpanTB.getText());
        
        
        
    }
    
    private void populateVocab(){
        try{
            for(String s:vocabProvider.getVocab("sites"))
                siteCB.addItem(s);

            for(String u:vocabProvider.getVocab("units"))
                unitCB.addItem(u);

            for(String s: vocabProvider.getVocab("sources"))
                sourceCB.addItem(s);

            for(String a: vocabProvider.getVocab("aggmethods"))
                aggMethodCB.addItem(a);

            offsetTypeCB.addItem("");//This is optional
            for(String o:vocabProvider.getVocab("offsettypes"))
                offsetTypeCB.addItem(o);

            for(String v:vocabProvider.getVocab("variables"))
                variableCB.addItem(v);
        }catch(Exception e){
            javax.swing.JOptionPane.showMessageDialog(null, e.getMessage());
        }
    }
    
    private void populateSelections(){
        
        try{
            if(columnObject.ignoreColumn())
                return;
            
            siteCB.setSelectedIndex(findMatchIndex(siteCB,val.getSite()));
            unitCB.setSelectedIndex(findMatchIndex(unitCB,val.getUnit()));
            sourceCB.setSelectedIndex(findMatchIndex(sourceCB,val.getSource()));
            aggMethodCB.setSelectedIndex(findMatchIndex(aggMethodCB,val.getAggMethod()));
            offsetTypeCB.setSelectedIndex(findMatchIndex(offsetTypeCB,val.getOffsetType()));
            variableCB.setSelectedIndex(findMatchIndex(
                    variableCB,vocabProvider.updateVocab("variables", val.getVariable())));
            duplicateCB.setSelectedIndex(val.getDuplicateID()-1);

            if(Double.compare(val.getOffsetValue(), Double.NaN) != 0){
                offsetTB.setText(Double.toString(val.getOffsetValue()));
            }
            
            utcOffsetTB.setText(Double.toString(val.getUtcOffset()));

            aggSpanTB.setText(val.getAggSpan());

            //-1 means no sensorid
            if(val.getSensorID() == -1){
                sensorTB.setText("");
            }else{
                sensorTB.setText(Integer.toString(val.getSensorID()));
            }
        }catch(Exception e){
            e.printStackTrace();
            javax.swing.JOptionPane.showMessageDialog(null, e.getMessage());
        }
        
    }
    
    private int findMatchIndex(javax.swing.JComboBox cb,String s){
        int index = -1;//This is default, if we don't find a match, -1 is returned
        
        for(int i=0; i<cb.getItemCount();i++){
            if(((String)cb.getItemAt(i)).compareToIgnoreCase(s)==0){
                index = i;
                break;
            }
        }
        
        return index;
    }
    
    public ValueObject getValueObject(){
        return val;
    }
}
